package com.vcens.dingnotice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.vcens.dingnotice.entity.MessageEntity;
import com.vcens.dingnotice.entity.TaskEntity;
import com.vcens.dingnotice.entity.TypeEntity;
import com.vcens.dingnotice.exception.RestException;
import com.vcens.dingnotice.repository.MessageMapper;
import com.vcens.dingnotice.repository.TaskerMapper;
import com.vcens.dingnotice.repository.TypeMapper;
import com.vcens.dingnotice.service.ITaskerService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @author vechar
 */
@Service
@Transactional
@Slf4j
public class TaskerServiceImpl implements ITaskerService {

    @Autowired
    private TaskerMapper taskerMapper;

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private TypeMapper typeMapper;

    @Autowired
    private Scheduler scheduler;

    @Override
    public void buildTask(Integer taskId) {
        log.info("DingNotice Init Task has been initialized...");
        CompletableFuture.runAsync(() -> {
            //任务详情
            TaskEntity taskEntity = taskerMapper.selectByTaskId(taskId);
            //消息列表
            List<MessageEntity> messageEntityList = messageMapper.selectByTaskId(taskEntity.getId());
            messageEntityList.stream().forEach(m -> {
                //创建任务信息
                try {
                    //任务类型
                    TypeEntity typeEntity = typeMapper.selectById(m.getTypeId());
                    Class cls = Class.forName(typeEntity.getClassName());
                    cls.newInstance();
                    JobDetail job = JobBuilder.newJob(cls).withIdentity(m.getId()+taskEntity.getName(),
                            m.getId()+taskEntity.getTaskGroup())
                            .withDescription(taskEntity.getTaskDesc()).build();
                    Map<String, Object> contentMap = (Map<String, Object>) JSONObject.parse(m.getContent());
                    if (contentMap != null) {
                        //传递消息ID
                        job.getJobDataMap().putAll(contentMap);
                    }
                    CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(taskEntity.getCronExpression());
                    Trigger trigger = TriggerBuilder.newTrigger().withIdentity(m.getId() + taskEntity.getName(), m.getId() + taskEntity.getTaskGroup())
                            .startNow().withSchedule(cronScheduleBuilder).build();
                    scheduler.scheduleJob(job, trigger);
                    taskerMapper.updateByTaskId(taskId);
                } catch (Exception e) {
                    log.error("构建任务异常", e);
                }
            });
        });
    }

    @Override
    public TaskEntity findById(Object jobid) {
        return null;
    }

    @Override
    public void triggerTask(TaskEntity taskEntity) throws RestException {
        JobKey key = new JobKey(taskEntity.getName(), taskEntity.getTaskGroup());
        try {
            scheduler.triggerJob(key);
        } catch (SchedulerException e) {
            throw new RestException("开启任务失败");
        }
    }

    @Override
    public List<TaskEntity> listByPage(TaskEntity taskEntity, Integer cp, Integer pageSize) {
        return null;
    }

    @Override
    public void pauseTask(TaskEntity taskEntity) throws RestException {
        JobKey key = new JobKey(taskEntity.getName(), taskEntity.getTaskGroup());
        try {
            scheduler.pauseJob(key);
        } catch (SchedulerException e) {
            throw new RestException("暂停任务失败");
        }
    }

    @Override
    public void resumeTask(TaskEntity taskEntity) throws RestException {
        JobKey key = new JobKey(taskEntity.getName(), taskEntity.getTaskGroup());
        try {
            scheduler.resumeJob(key);
        } catch (SchedulerException e) {
            throw new RestException("恢复任务失败");
        }
    }

    @Override
    public void removeTask(TaskEntity taskEntity) throws RestException {
        TriggerKey triggerKey = TriggerKey.triggerKey(taskEntity.getName(), taskEntity.getTaskGroup());
        // 停止触发器
        try {
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(taskEntity.getName(), taskEntity.getTaskGroup()));
        } catch (SchedulerException e) {
            throw new RestException("删除任务失败");
        }
    }

    @Override
    public List<Map<String, Object>> list() throws RestException {
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = null;
        List<Map<String, Object>> jobList = new ArrayList<>();
        try {
            jobKeys = scheduler.getJobKeys(matcher);
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    Map<String, Object> job = new HashMap<>();
                    job.put("Name", jobKey.getName());
                    job.put("group", jobKey.getGroup());
                    //下次触发时间
                    job.put("NextTime", trigger.getNextFireTime());
                    //上次触发时间
                    job.put("lastTime", trigger.getPreviousFireTime());
                    //开始时间
                    job.put("startTime", trigger.getStartTime());
                    //trigger.getEndTime();//结束时间
                    //触发器当前状态
                    Trigger.TriggerState triggerState = null;
                    try {
                        triggerState = scheduler.getTriggerState(trigger.getKey());
                    } catch (SchedulerException e) {
                        e.printStackTrace();
                    }
                    job.put("triggerState", triggerState.name());
                    //任务表达式
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        job.put("cronExpression", cronExpression);
                    }
                    jobList.add(job);
                }
            }
        } catch (SchedulerException e) {
            throw new RestException("获取任务列表异常");
        }
        return jobList;
    }

    @Override
    public boolean create(TaskEntity taskEntity) {
        int insert = taskerMapper.insert(taskEntity);
        return insert > 0;
    }
}
